package JHfstools;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;

import javax.swing.JOptionPane;
import javax.swing.SwingWorker;
import javax.swing.border.TitledBorder;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;

import org.apache.commons.net.PrintCommandListener;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPListParseEngine;
import org.apache.commons.net.io.CopyStreamAdapter;




// This class is used to perform remote functions when using an FTP connection.
public class hftftp {
	public hftftp(){
	// dummy constructor	
	}
	static FTPClient ftp = null;
	static String remoteDirPath = null;
	static int beginnewpath = 0;
	static String originaldir= null;
	static FileOutputStream logs = null;
	static BufferedOutputStream bls = null;
	static PrintStream pls = null;
	
	public static void ftpsetup(){
		int reply= 0;
		if (logs == null){
		try {
			logs = new FileOutputStream("ftplog.txt");
			bls = new BufferedOutputStream(logs);
			pls = new PrintStream(bls);
			System.setOut(pls);
		} catch (FileNotFoundException e2) {
			e2.printStackTrace();
		}
		}
		hftmain.logopen = true;
		ftp = new FTPClient();
		//ftp.enterLocalPassiveMode();
		ftp.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out),true));
		if (hftmain.gotd == false){
			hftsecdlg sec = new hftsecdlg(hftmain.d.targstr);
			sec.pack();
			sec.setLocationRelativeTo(null);
			sec.setVisible(true);
			hftmain.d.settarg(sec.getJHFSsectargbox().getSelectedItem().toString());
			hftmain.d.setuid(sec.getJHFSsecuid().getText());
			hftmain.d.setpswd(sec.getJHFSsecpswd().getText());
		}
		String here2 = hftmain.d.gettarg().toString();
		hftmain.hftstatus.setText("Connecting to "+hftmain.d.Targsys);
		hftmain.hftstatus.invalidate();
		try {
			ftp.connect(hftmain.d.Targsys,21);
			System.out.println(ftp.getReplyString());
			reply = ftp.getReplyCode();
			//hftstatus.setText("reply code is"+reply);
			ftp.login(hftmain.d.getuid(), hftmain.d.getpswd());
			int crc = ftp.getReplyCode();
			System.out.println(crc);
			hftmain.hftstatus.setText("Reply code is"+crc);
			hftmain.hftstatus.invalidate();
			if (crc == 530){
				hftmain.appendNewText("Password was invalid, use security button to change it.");
			}
			System.out.println(ftp.getReplyString());
			String buff = ftp.getSystemType();
			if (buff.indexOf("Windows") != -1){hftmain.twindows=true; hftmain.tslash="\\";}
			else{hftmain.tslash="/";}
			System.out.println(ftp.getReplyString());
			originaldir = ftp.printWorkingDirectory();
			ftp.setBufferSize(0);
			System.out.println(ftp.getReplyString());
			//if (hftpsvbtn.isSelected()){ftp.enterLocalPassiveMode(); }
			//ftp.enterLocalActiveMode();
			ftp.enterLocalPassiveMode();
			ftp.setControlKeepAliveTimeout(288);
			System.out.println(ftp.getReplyString());
		} catch (IOException e) {
			e.printStackTrace();
		}
		hftmain.ftpconn = true;
		hftmain.rroot = new DefaultMutableTreeNode(originaldir,true);
		if (hftmain.hfttargtree != null){
			hftmain.hfttargtree.setBorder(new TitledBorder(null, hftmain.d.Targsys, TitledBorder.LEADING, TitledBorder.TOP, null, null));
		}
		hftmain.newr = new FTPFile();
		try {
			hftmain.newr.setName(ftp.printWorkingDirectory());
			hftmain.idir = ftp.printWorkingDirectory();
		} catch (IOException e) {
			e.printStackTrace();
		}
		getFtpList(hftmain.rroot);
	
	}
	/* This method list all files and directories in the remote directory passed in F.  It only lists the first level to make it run faster
	 * and to prevent security issues.  This requires using a custom JTree CellRenderer. 
	 */
	public static void getFtpList(DefaultMutableTreeNode node) {
		//ftp.setListHiddenFiles(true);
		boolean lh  = ftp.getListHiddenFiles();
		String dave = node.toString();
		
		try {
			dave = ftp.printWorkingDirectory();
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
	    FTPFile[] fList = null; 
	    hftmain.hftstatus.setText(" ");
	    try {
	    	FTPListParseEngine engine = ftp.initiateListParsing("UnixFTPEntryParser", "-al");
	    	fList = engine.getFiles();
			if (fList.length == 0 && dave !="/" && hftmain.ftpconn){
				hftmain.hftstatus.setText("Selected Directory is empty.");
			}
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			return;
		} catch (NullPointerException e){
			//node.add(child);
			return;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	     for(int i = 0; i  < fList.length; i++){
	    	 if (fList[i].hasPermission(FTPFile.USER_ACCESS,FTPFile.READ_PERMISSION) == false){
	    		 hftmain.hftstatus.setText("Security error listing directory "+fList[i].getName());
	    		 continue;}
	    	 String fn = fList[i].getName().toString();
	    	 DefaultMutableTreeNode nn = new DefaultMutableTreeNode(fn);
	    	 if (fList[i].isFile()){nn.setAllowsChildren(false);}
	    	 if (fList[i].isDirectory()){nn.setAllowsChildren(true);}
	    	 if (fList[i].isSymbolicLink()){nn.setAllowsChildren(false);}
	    	 if (fList[i].hasPermission(FTPFile.USER_ACCESS, FTPFile.READ_PERMISSION) && node.getUserObject().toString() != nn.getUserObject().toString()){
	    		 node.add(nn);
	    	 }
		}
		}
	
	public static void dobg(){
		hftftp x = new hftftp();
		if (!hftmain.reversecopy){
			hftmain.appendNewText("Copying files...");
		doFTPtcopy ti = x.new doFTPtcopy();
		ti.execute();
		} // standard source to target copy
		if (hftmain.reversecopy){
			hftmain.appendNewText("Copying files...");
			doFTPrcopy ti = x.new doFTPrcopy();
			ti.execute();
		}
	}
	
	/* this class is used to FTP user selected directories and files from the source system to the target system. */
	public class doFTPtcopy extends SwingWorker<Integer, String>{
		protected Integer doInBackground() throws Exception{
			ftp.changeWorkingDirectory(hftmain.newr.getName());
			DefaultMutableTreeNode tnode = null;
			DefaultMutableTreeNode node = null;
			boolean singlefile = false;
			FTPFile[] ftpf;
			TreeSelectionListener[] tester = hftmain.hfttargtree.getTreeSelectionListeners();
			if (hftmain.hfttargtree.getLastSelectedPathComponent() == null){
				JOptionPane.showMessageDialog(hftmain.contentPane,"Please select an output directory","Copy error",JOptionPane.ERROR_MESSAGE);
				return null;	
			}
			tnode = (DefaultMutableTreeNode) hftmain.hfttargtree.getLastSelectedPathComponent();
			node = (DefaultMutableTreeNode) hftmain.hftsrctree.getLastSelectedPathComponent();
			String nfn = node.getUserObject().toString(); // get new file name
			File srcselfile = new File(nfn); // create file object based on name
			if (srcselfile.isFile()){singlefile=true;} // if user selected a file, we are only copying a single file
			if ((hftmain.twindows != hftmain.swindows) && !singlefile){ // If we have two different operating systems, nd the user selected a directory
				dircopywarn dcw = new dircopywarn(); // warn the user that directory copies are done in binary mode, not ASCII
				dcw.pack();
				dcw.setLocationRelativeTo(null);
				dcw.setVisible(true); // display the dialog box
				if (!dcw.getrc()){hftmain.docopycan();} // find out if user clicked OK or cancel
				}
			hftmain.hftstatus.setText("Gathering source file information...");
			if (!singlefile){
				remoteDirPath = ftp.printWorkingDirectory()+"/"+tnode.toString();
			}else{
				remoteDirPath = ftp.printWorkingDirectory();
			}
			hftmain.localDirPath = node.getUserObject().toString();
			String fnode = node.toString();
			if(hftmain.swindows){
			beginnewpath = hftmain.localDirPath.lastIndexOf("\\");
			}else{
				beginnewpath = hftmain.localDirPath.lastIndexOf("/");
			}
			beginnewpath+=1;
			hftmain.skippath = hftmain.localDirPath.substring(0, beginnewpath);
			fnode = hftmain.localDirPath.substring(beginnewpath);
			ftp.cwd(remoteDirPath);
			String nwd = null;
			if (!singlefile){
			nwd = node.toString()+hftmain.sslash;
			nwd = nwd.substring(beginnewpath);
			DefaultMutableTreeNode wnode = node;
			while (!wnode.getParent().toString().equals("..")){
				wnode = (DefaultMutableTreeNode) wnode.getParent();
				String twd = wnode.toString();
				nwd = twd + hftmain.sslash + nwd;
			}
			}
			if (singlefile){// user selected a single file, just transfer it
			if (hftmain.hftascbtn.isSelected()){ftp.setFileType(FTP.ASCII_FILE_TYPE);}
			if (hftmain.hftbinbtn.isSelected()){ftp.setFileType(FTP.BINARY_FILE_TYPE);}
			nwd = tnode.toString()+"/";
			DefaultMutableTreeNode wnode = tnode;
			while (!wnode.getParent().toString().equals("..") && !wnode.getParent().toString().equals(remoteDirPath)){
				wnode = (DefaultMutableTreeNode) wnode.getParent();
				String twd = wnode.toString();
				nwd = twd + "/" + nwd;
			}
	        String localFilePath = srcselfile.getAbsolutePath();
	        hftmain.totlength = srcselfile.length();
	        hftmain.totleft = hftmain.totlength;
	        String remoteFilePath = remoteDirPath+"/"+nwd+srcselfile.getName();
	        hftmain.hftstatus.setText("About to copy file "+localFilePath);
	        boolean uploaded = FTPUtil.uploadSingleFile(ftp,
	                localFilePath, remoteFilePath);
	        if (uploaded) {
	            System.out.println("Copied file: "+ remoteFilePath);
	            hftmain.hftstatus.setText("Copied file "+localFilePath);
	            hftmain.hftallfileprog.setValue(100);
	        } else {
	        	hftmain.hftstatus.setText("FTP error occured, check the log");
	            System.out.println("Could not copy file: "+ localFilePath);
	        }
			}else{// user selected a directory, so walk the directory and copy files.
			if (!hftmain.swindows){hftmain.localDirPath+="/";}
			ftpf = ftp.listFiles(fnode);
			if (ftpf.length== 0){
				int mrc = ftp.mkd(fnode);
				int y= 2;}
			Filewalker fw = new Filewalker();
			hftmain.dirnewpath=beginnewpath+fnode.length();
			fw.walklen(hftmain.localDirPath);
			ftp.cwd(fnode);
			hftmain.totleft=hftmain.totlength;
			hftmain.rdir = remoteDirPath+"/"+fnode;
			FTPUtil.uploadDirectory(ftp, remoteDirPath, hftmain.localDirPath, fnode);
	}
			if (!singlefile){
				hftmain.hftstatus.setText("Directory "+hftmain.localDirPath+" was copied to "+remoteDirPath);
				hftmain.hftallfileprog.setValue(100);
				if (hftmain.copyerror){
					hftmain.hftstatus.setText("Directory "+hftmain.localDirPath+" copied to "+remoteDirPath+" with errors.  Plese check log.");
				}
			}
			return hftmain.pi;
			
		}
	}
	
	/* this class is used to FTP user selected directories and files from the target system to the source system. */
	public class doFTPrcopy extends SwingWorker<Integer, String>{
		protected Integer doInBackground() throws Exception{
			ftp.changeWorkingDirectory(hftmain.newr.getName());
			DefaultMutableTreeNode tnode = null;
			DefaultMutableTreeNode node = null;
			DefaultMutableTreeNode pnode = null;
			FTPFile[] ftpf;
			if (hftmain.hfttargtree.getLastSelectedPathComponent() == null && hftmain.hftsrctree.getLastSelectedPathComponent() == null){
				JOptionPane.showMessageDialog(hftmain.contentPane,"Please select an output directory","Copy error",JOptionPane.ERROR_MESSAGE);
				return null;	
			}
			tnode = (DefaultMutableTreeNode) hftmain.hftsrctree.getLastSelectedPathComponent();
			node = (DefaultMutableTreeNode) hftmain.hfttargtree.getLastSelectedPathComponent();
			hftmain.originalnode = node;
			if (node.isLeaf()){hftmain.singlefile=true;} // if user selected a file, we are only copying a single file
			DefaultMutableTreeNode worknode = new DefaultMutableTreeNode();
			int pl = node.getLevel();
			String rcd = null;
			String parentdir= "";
			if (hftmain.singlefile && pl > 1){parentdir = node.getParent().toString();}		
			else {parentdir = node.toString();}
			if (!hftmain.singlefile){
			if (node.getLevel() >2){parentdir=node.getParent().toString();}
			parentdir+=hftmain.tslash;		
			if (pl > 2){worknode = (DefaultMutableTreeNode) node.getParent();}
			if (pl >1){
			while (pl > 0){
				String tstr = parentdir;
				parentdir=worknode.toString()+hftmain.tslash+tstr;
				worknode = (DefaultMutableTreeNode) worknode.getParent();
				pl = worknode.getLevel();
			}
			rcd = parentdir;
			}
			if (pl > 1){
				pnode = (DefaultMutableTreeNode) node.getParent();
			}else
			{pnode = node;
			}
		
			if (pl == 1){rcd = pnode.toString();}		
			//String parentdir = pnode.toString();
			hftmain.nfn = node.getUserObject().toString(); // get new file name
			if ((hftmain.twindows != hftmain.swindows) && !hftmain.singlefile){ // If we have two different operating systems, and the user selected a directory
				dircopywarn dcw = new dircopywarn(); // warn the user that directory copies are done in binary mode, not ASCII
				dcw.pack();
				dcw.setLocationRelativeTo(null);
				dcw.setVisible(true); // display the dialog box
				if (!dcw.getrc()){hftmain.docopycan();} // find out if user clicked OK or cancel
				}
			}
			hftmain.hftstatus.setText("Gathering source file information...");
			//FTPUtil.downloadDirectory(ftp, "Source", "", "c:\\davetest\\");
			//FTPUtil.downloadDirectory(ftp, nfn, "", tnode.getUserObject().toString());
			if (!hftmain.singlefile){
			remoteDirPath = ftp.printWorkingDirectory()+hftmain.tslash+parentdir;
			}else{
				remoteDirPath = ftp.printWorkingDirectory();
			}
			hftmain.localDirPath = tnode.getUserObject().toString();
			String fnode = node.toString();
			if(hftmain.twindows){
			beginnewpath = remoteDirPath.lastIndexOf("\\");
			}else{
				beginnewpath = remoteDirPath.lastIndexOf("/");
			}
			beginnewpath+=1;
			hftmain.skippath = remoteDirPath.substring(0, beginnewpath);
			FTPFile srcselfile = new FTPFile();
			if (!hftmain.singlefile){
				FTPFile[] fls = ftp.listFiles(hftmain.newr.getName()); // list remote files with that name
				for (int i = 0; i < fls.length; i++){
					if (fls[i].getName().equals(hftmain.nfn)){	
					srcselfile = fls[i]; // our file is the first one in the array
					}// end of if
				} // end of for
				}
				if (hftmain.singlefile){  // for a single file we need to construct the path names
					FTPFile[] tfile = new FTPFile[1];
					String npath = "/"; 
					Object[] oa = node.getUserObjectPath();
					for (int i = 1; i < oa.length; i++){
						npath = npath+oa[i]+"/"; 
					}
					hftmain.singlefilename = ftp.printWorkingDirectory()+npath.substring(0,npath.length()-1);
					tfile = ftp.listFiles(hftmain.singlefilename); // list remote file to get properties
					srcselfile = tfile[0]; //and save it in our source file name.
				}
			String nwd = null;
			if (!hftmain.singlefile){nwd = node.toString()+hftmain.tslash;}
			DefaultMutableTreeNode wnode = node;
			while (!(wnode.getLevel() == 1)){
				wnode = (DefaultMutableTreeNode) wnode.getParent();
				String twd = wnode.toString();
				nwd = twd + hftmain.tslash + nwd;
			}
			if (hftmain.singlefile){// user selected a single file, just transfer it
			if (hftmain.hftascbtn.isSelected()){ftp.setFileType(FTP.ASCII_FILE_TYPE);}
			if (hftmain.hftbinbtn.isSelected()){ftp.setFileType(FTP.BINARY_FILE_TYPE);}
			int bytestran =0;
			if (srcselfile.getSize() == 0){// if file is empty, create a new empty file.
				File ef = null;
				ef = new File(hftmain.localDirPath+hftmain.sslash+fnode);
				if (!ef.exists()){
					ef.createNewFile();
				}
				hftmain.hftcurrfileprog.setValue(100);
				hftmain.hftallfileprog.setValue(100);
				hftmain.hftstatus.setText("Empty file "+fnode+" copied to "+remoteDirPath);
			}// end if srcselfile.length == 0
			if (srcselfile.getSize() > 0){
			InputStream is;
			if (!hftmain.twindows && !hftmain.singlefile){remoteDirPath+="/";}
			ftp.changeWorkingDirectory(remoteDirPath);
			is = ftp.retrieveFileStream(hftmain.singlefilename);
			OutputStream os = new FileOutputStream(hftmain.localDirPath+"\\"+fnode); 
			String msg = ftp.getReplyString();
			long filelen = srcselfile.getSize();
			System.out.println(ftp.getReplyString());
			long left = (long) (filelen/1.0);
			byte[] buffer=null;
			if (os == null){hftmain.hftstatus.setText("Could not get output stream, check log.");}
			else{
				hftmain.hftstatus.setText("Copying file "+fnode);
				System.out.println("input directory is "+remoteDirPath+hftmain.tslash+nwd);
			}
			if (filelen > 500){
			buffer = new byte[(int) (filelen/10)];
			}else {
			buffer = new byte[(int) filelen];
			}
			int len;  
			while ((len = is.read(buffer)) != -1)  
			{
			    os.write(buffer, 0, len);
			    os.flush();
			    bytestran += len;
			    if (filelen > 100){
			    left = left-(filelen/10);
			    }else{
			    	left=0;
			    }
			    double ip = (left*100)/filelen;
			    int percomp =  (int) (100-ip);
			    hftmain.hftcurrfileprog.setValue(percomp);
			    hftmain.hftallfileprog.setValue(percomp);
			    if (bytestran == filelen){break;}
				}
				os.flush();
				os.close();
				is.close();
				ftp.completePendingCommand();
				System.out.println("File "+fnode+" was copied from "+remoteDirPath+hftmain.tslash+nwd+" to "+hftmain.localDirPath+".");
				hftmain.totleft = 0;
			    double ip = (left*100)/filelen;
			    int percomp =  (int) (100-ip);
			    int perallcomp = 100;
			    hftmain.hftcurrfileprog.setValue(percomp);
			    hftmain.hftallfileprog.setValue(perallcomp);
			    hftmain.hftstatus.setText("file "+fnode+" copied to directory "+hftmain.localDirPath);
				}// end if srcselfile.length > 0
			}else{// user selected a directory, so walk the directory and copy files.
				hftmain.localDirPath+=hftmain.sslash;
			ftp.changeWorkingDirectory(rcd);
			ftp.cdup();
			ftpf = ftp.listFiles(fnode);
			long[] dirInfo = FTPUtil.calculateDirectoryInfo(ftp,rcd,"");
			System.out.println("Total Dirs = "+dirInfo[0]);
			System.out.println("Total Files = "+dirInfo[1]);
			System.out.println("Total Size = "+dirInfo[2]);
			hftmain.totlength = dirInfo[2];
			hftmain.totleft = hftmain.totlength;
			ftp.changeWorkingDirectory(hftmain.rroot.toString());
			FTPUtil.downloadDirectory(ftp, rcd, "",hftmain.localDirPath);
	}
			if (!hftmain.singlefile){
				hftmain.hftstatus.setText("Directory "+remoteDirPath+" was copied to "+hftmain.localDirPath);
				System.out.println("Total files copied = "+hftmain.totcopied);
				System.out.println("Total bytes copied = "+hftmain.totlength);
				if (hftmain.copyerror){
					hftmain.hftstatus.setText("Directory "+hftmain.localDirPath+" copied to "+remoteDirPath+" with errors.  Plese chack log.");
				}
			}
			return hftmain.pi;
			
		}
	}

	
	public class Filewalker {
		/* this class is used to walk the file system during transfers when a directory is selected instead of a file. */
		    public void walklen( String path ) {
		// This method counts up the total bytes in a selected directory and its subdirectories for use in progress bars.
		        File root = new File( path );
		        File[] list = root.listFiles();
		        if (list == null) return;
		        for ( File f : list ) {
		            if ( f.isDirectory() ) {
		                walklen( f.getAbsolutePath() );
		                
		            }
		            else {
		                hftmain.totlength += f.length();
		                hftmain.totfiles +=1;
		            }
		        }
		    }

		}
	public static void doFTPTargtreeclicked(DefaultMutableTreeNode tnode){
		hftmain.d.setltc("target"); // last tree clicked was the target
		DefaultMutableTreeNode sp = new DefaultMutableTreeNode(tnode.getParent());
		DefaultTreeModel dtm = new DefaultTreeModel(tnode);
		String sel = (String) tnode.toString();
		String dsel = null;
		if (sel.equals("..")){
			hftmain.hftstatus.setText("Reading remote file system...");

			try {
				ftp.cdup();
				dsel = ftp.printWorkingDirectory();
				if (dsel.equals("/")){
					hftmain.appendNewText("Already at root, cannot change directory");
				}
			} catch (IOException e2) {
				// TODO Auto-generated catch block
				e2.printStackTrace();
			}
			dtm.nodeChanged(hftmain.rroot);
			dtm.nodeStructureChanged(hftmain.rroot);
			dtm.setRoot(null);
			hftmain.rroot.setUserObject(dsel);
			dtm.setRoot(hftmain.rroot);
        	dtm.nodeChanged(hftmain.rroot);
			dtm.reload(hftmain.rroot);
			hftftp.getFtpList(hftmain.rroot);
			dtm.reload();
			dtm.nodeStructureChanged(hftmain.rroot);
			dtm.nodeChanged(hftmain.rroot);
			hftmain.hfttargtree.invalidate();
		}
		if (tnode.getAllowsChildren()&& !sel.equals("..")){
		try {
			// If parent of the node clicked on is the root, we have a new node path
			String nn = tnode.toString();
			if (tnode.isRoot()){
				ftp.cwd(sel); // so switch back to the starting root.
				String db = ftp.getReplyString();
				String dp = ftp.printWorkingDirectory();
			}else{
			if (tnode.getLevel() == 1){//only do this if the user clicked
			//DefaultTreeModel dtm = (DefaultTreeModel) hfttargtree.getModel(); // on a different node
				if (hftmain.oldtnode != null){//if a node was previously selected, remove its children from the model before we load the 
					hftmain.oldtnode.removeAllChildren(); // children of the newly selected node.
					dtm.nodeChanged(hftmain.oldtnode);
					dtm.reload();
					int nodelev = tnode.getLevel();
					int oldnodelev = hftmain.oldtnode.getLevel();
					if (nodelev == 1 && oldnodelev == 0){ftp.cwd(sel);}
					if (nodelev == 1 && oldnodelev >0){
						String noden = null;
						if (hftmain.twindows){
						noden = "\\"+tnode.toString();
						}else
						{
						noden = "/"+tnode.toString();
						}
						ftp.cwd(noden);
						String em = ftp.getReplyString();
						int a= 0;
						} // if new node level is one, parent is the root so change to it.
					else{
						int upnum = oldnodelev - nodelev;
						int l = 0;
						while ( l < upnum){
							ftp.cdup();
							l++;
						}
					}
				}
			}//end else
			}// end else
			ftp.cwd(sel); // change to the directory the user clicked on
			ftp.printWorkingDirectory();
			String pwd = ftp.printWorkingDirectory();
			int j = 0;
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		hftftp.getFtpList(tnode);
		dtm.reload(tnode);
		}
		hftmain.d.setsel(sel);
		hftmain.d.setparent(sp);
		hftmain.d.setfl("remote");
		hftmain.oldtnode = tnode;
	}

	/**
	 * This utility class provides a method that creates a nested directory
	 * structure on a FTP server, based on Apache Commons Net library.
	 *
	 */
	public static class FTPUtil {
	    /**
	     * Creates a nested directory structure on a FTP server
	     * @param ftpClient an instance of org.apache.commons.net.ftp.FTPClient class.
	     * @param dirPath Path of the directory, i.e /projects/java/ftp/demo
	     * @return true if the directory was created successfully, false otherwise
	     * @throws IOException if any error occurred during client-server communication
	     */
	    public static boolean makeDirectories(FTPClient ftpClient, String dirPath)
	            throws IOException {
	    	
	    	String[] pathElements = null;
	    	if (hftmain.twindows){
	        pathElements = dirPath.split("\\");
	    	}else{
	    	       pathElements = dirPath.split("/");	
	    	}
	        if (pathElements != null && pathElements.length > 0) {
	            for (String singleDir : pathElements) {
	            	if (singleDir.equals("")){singleDir = "/";}
	                boolean existed = ftpClient.changeWorkingDirectory(singleDir);
	                if (!existed) {
	                    boolean created = ftpClient.makeDirectory(singleDir);
	                    if (created) {
	                        System.out.println(ftpClient.getReplyString());
	                        ftpClient.changeWorkingDirectory(singleDir);
	                    } else {
	                        System.out.println(ftpClient.getReplyString());
	                        return false;
	                    }
	                }
	            }
	        }
	        return true;
	    }
	    /**
	     * Upload a whole directory (including its nested sub directories and files)
	     * to a FTP server.
	     *
	     * @param ftpClient
	     *            an instance of org.apache.commons.net.ftp.FTPClient class.
	     * @param remoteDirPath
	     *            Path of the destination directory on the server.
	     * @param localParentDir
	     *            Path of the local directory being uploaded.
	     * @param remoteParentDir
	     *            Path of the parent directory of the current directory on the
	     *            server (used by recursive calls).
	     * @throws IOException
	     *             if any network or IO error occurred.
	     */
	    public static void uploadDirectory(FTPClient ftpClient,
	            String remoteDirPath, String localParentDir, String remoteParentDir)
	            throws IOException {
	    	int rc= 0;
	        File localDir = new File(localParentDir);
	        File[] subFiles = localDir.listFiles();
	        if (subFiles != null && subFiles.length > 0) {
	            for (File item : subFiles) {
	                String remoteFilePath = remoteDirPath + "/" + remoteParentDir
	                        + "/" + item.getName();
	                if (remoteParentDir.equals("")) {
	                    remoteFilePath = remoteDirPath + "/" + item.getName();
	                }
	     
	     
	                if (item.isFile()) {
	                    // upload the file
	                    String localFilePath = item.getAbsolutePath();
	                    System.out.println("Copying file: " + localFilePath);
	                    hftmain.hftstatus.setText("Copying file "+localFilePath);
	                    boolean uploaded = uploadSingleFile(ftpClient,
	                            localFilePath, remoteFilePath);
	                    if (uploaded) {
	                    	hftmain.hftstatus.setText("Copied file "+localFilePath);
	                    } else {
	                        System.out.println(ftpClient.getReplyString());
	                        rc = ftpClient.getReplyCode();
	                        hftmain.ftperror = true;
	                    }
	                } else {
	                    // create directory on the server
	                    boolean created = ftpClient.makeDirectory(remoteFilePath);
	                    if (created) {
	                        System.out.println(ftpClient.getReplyString());
	                    } else {
	                        System.out.println(ftpClient.getReplyString());
	                    }
	     
	                    // upload the sub directory
	                    String parent = remoteParentDir + "/" + item.getName();
	                    if (remoteParentDir.equals("")) {
	                        parent = item.getName();
	                    }
	     
	                    localParentDir = item.getAbsolutePath();
	                    uploadDirectory(ftpClient, remoteDirPath, localParentDir,
	                            parent);
	                }
	                if (rc == 451){hftmain.hftstatus.setText("Copy error, output device out of space.  Check Log");}
	                if (hftmain.ftperror){hftmain.hftstatus.setText("FTP transfer error, check log.");} 
	            }
	        }
	    }
	    /**
	     * Upload a single file to the FTP server.
	     *
	     * @param ftpClient
	     *            an instance of org.apache.commons.net.ftp.FTPClient class.
	     * @param localFilePath
	     *            Path of the file on local computer
	     * @param remoteFilePath
	     *            Path of the file on remote the server
	     * @return true if the file was uploaded successfully, false otherwise
	     * @throws IOException
	     *             if any network or IO error occurred.
	     */
	    public static boolean uploadSingleFile(FTPClient ftpClient,
	            String localFilePath, String remoteFilePath) throws IOException {
	        final File f = new File(localFilePath);
			if (f.length() == 0){// input file is zero length so just create an empty file on the server
				FTPFile nf = new FTPFile();
				nf.setName(remoteFilePath);
				nf.setSize(0);
				nf.setType(FTPFile.FILE_TYPE);
				OutputStream os;
				String tfn = null;
				String olddir = ftpClient.printWorkingDirectory();
				int pb = remoteFilePath.lastIndexOf("/");
				String np = remoteFilePath.substring(0,pb);
				tfn = remoteFilePath.substring(pb+1);
				ftpClient.changeWorkingDirectory(np);
				String dave = ftpClient.printWorkingDirectory();
				//tfn = f.getName();
				try {
				os = ftpClient.appendFileStream(tfn);
				String rc = ftpClient.getReplyString();
				os.flush();
				rc = ftpClient.getReplyString();
				os.close();
				rc = ftpClient.getReplyString();
				System.out.println("file transfer rc was "+rc);
				ftpClient.completePendingCommand();
				}catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				hftmain.hftcurrfileprog.setValue(100);
				hftmain.hftstatus.setText("Empty file "+f.getName()+" copied to "+remoteDirPath);
				ftpClient.changeWorkingDirectory(olddir);
				return true;
			}else{// end of if f.legnth() == 0
			CopyStreamAdapter listener = new CopyStreamAdapter(){
				 @Override
				    public void bytesTransferred(long totalBytesTransferred, int bytesTransferred, long streamSize) {
				       //this method will be called everytime some bytes are transferred
					   long fs  = f.length();
					   String fn = f.getName();
				       int percent = (int)(totalBytesTransferred*100/f.length());
				       hftmain.totleft -= bytesTransferred;
					   double ap = (hftmain.totleft*100)/hftmain.totlength;
					   int perallcomp = (int) (99-ap);
					   hftmain.hftcurrfileprog.setValue(percent);
					   hftmain.hftallfileprog.setValue(perallcomp);
				       // update your progress bar with this percentage
				    }
			};

		    ftpClient.setCopyStreamListener(listener);
	        InputStream inputStream = new FileInputStream(f);
	        hftmain.hftstatus.setText("Copying file "+remoteFilePath);
	        try {
	            //ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
	            boolean crc;
	            crc = ftpClient.storeFile(remoteFilePath, inputStream);
	            System.out.println(ftpClient.getReplyString());
	            return crc;
	        } finally {
	            inputStream.close();
	        }
			}
	    }
	    /**
	     * Download a single file from the FTP server
	     * @param ftpClient an instance of org.apache.commons.net.ftp.FTPClient class.
	     * @param remoteFilePath path of the file on the server
	     * @param savePath path of directory where the file will be stored
	     * @return true if the file was downloaded successfully, false otherwise
	     * @throws IOException if any network or IO error occurred.
	     */
	    public static boolean downloadSingleFile(FTPClient ftpClient,
	            String remoteFilePath, String savePath) throws IOException {
	        File downloadFile = new File(savePath);
	         
	        File parentDir = downloadFile.getParentFile();
	        if (!parentDir.exists()) {
	            parentDir.mkdir();
	        }
		 	FTPListParseEngine engine = ftpClient.initiateListParsing("UnixFTPEntryParser", remoteFilePath);
		 	FTPFile [] fls = engine.getNext(1);
		 	final FTPFile f = fls[0];
	        OutputStream outputStream = new BufferedOutputStream(
	                new FileOutputStream(downloadFile));
			CopyStreamAdapter listener = new CopyStreamAdapter(){
				 @Override
				    public void bytesTransferred(long totalBytesTransferred, int bytesTransferred, long streamSize) {
				       //this method will be called everytime some bytes are transferred
					   long fs  = f.getSize();
					   String fn = f.getName();
					   hftmain.hftstatus.setText("Transferring file "+fn);
				       int percent = (int)(totalBytesTransferred*100/f.getSize());
				       hftmain.totleft -= bytesTransferred;
					   double ap = (hftmain.totleft*100)/hftmain.totlength;
					   int perallcomp = (int) (100-ap);
					   hftmain.hftcurrfileprog.setValue(percent);
					   hftmain.hftallfileprog.setValue(perallcomp);
				       // update your progress bar with this percentage
				    }
			};
			ftpClient.setCopyStreamListener(listener);
	        try {
	        	if (!hftmain.singlefile){ftpClient.setFileType(FTP.BINARY_FILE_TYPE);}
	        	else{
	        		if (hftmain.hftbinbtn.isSelected()){ftpClient.setFileType(FTP.BINARY_FILE_TYPE);}
	        		if (hftmain.hftascbtn.isSelected()){ftpClient.setFileType(FTP.ASCII_FILE_TYPE);}
	        		if (hftmain.hftebcbtn.isSelected()){ftpClient.setFileType(FTP.EBCDIC_FILE_TYPE);}
	        	}
	            return ftpClient.retrieveFile(remoteFilePath, outputStream);
	        } catch (IOException ex) {
	            throw ex;
	        } finally {
	            if (outputStream != null) {
	                outputStream.close();
	                hftmain.totcopied+=1;
	            }
	        }
	    }

	 /**
	 * Download a whole directory from a FTP server.
	 * @param ftpClient an instance of org.apache.commons.net.ftp.FTPClient class.
	 * @param parentDir Path of the parent directory of the current directory being
	 * downloaded.
	 * @param currentDir Path of the current directory being downloaded.
	 * @param saveDir path of directory where the whole remote directory will be
	 * downloaded and saved.
	 * @throws IOException if any network or IO error occurred.
	 */
	public static void downloadDirectory(FTPClient ftpClient, String parentDir,
	        String currentDir, String saveDir) throws IOException {
	    String dirToList = parentDir;
	    if (!currentDir.equals("")) {
	        dirToList += "/" + currentDir;
	    }
	    if (!currentDir.equals("")){
	    ftpClient.changeWorkingDirectory(currentDir);
	    }else{
	    	ftpClient.changeWorkingDirectory(dirToList);	
	    }
	    //FTPFile[] subFiles = ftpClient.listFiles(dirToList);
	    	//if (currentDir != ""){ftpClient.changeWorkingDirectory(currentDir);}
		 	FTPListParseEngine engine = ftpClient.initiateListParsing("UnixFTPEntryParser", "-al");
		 	FTPFile [] subFiles = engine.getFiles();
	 
	    if (subFiles != null && subFiles.length > 0) {
	        for (FTPFile aFile : subFiles) {
	            String currentFileName = aFile.getName();
	            if (currentFileName.equals(".") || currentFileName.equals("..")) {
	                // skip parent directory and the directory itself
	                continue;
	            }
	            String filePath = parentDir + "/" + currentDir + "/"
	                    + currentFileName;
	/*            if (currentDir.equals("")) {
	                filePath = parentDir + "/" + currentFileName;
	            }
	*/
	            filePath = currentFileName;
	            String newDirPath = saveDir + parentDir + File.separator
	                    + currentDir + File.separator + currentFileName;
	            if (currentDir.equals("")) {
	                newDirPath = saveDir + parentDir + File.separator
	                          + currentFileName;
	            }

	            if (aFile.isDirectory()) {
	                // create the directory in saveDir
	                File newDir = new File(newDirPath);
	                boolean created = newDir.mkdirs();
	                if (created) {
	                    System.out.println("CREATED the directory: " + newDirPath);
	                } else {
	                    System.out.println("COULD NOT create the directory: " + newDirPath);
	                }
	 
	                // download the sub directory
	                downloadDirectory(ftpClient, dirToList, currentFileName,
	                        saveDir);
	            } else {
	                int posx = filePath.indexOf(" ");
	                if (posx != -1){
	                	filePath = "'"+originaldir+"/"+parentDir+"/"+currentDir+"/"+filePath+"'";
	                }
	                // download the file
	                boolean success = downloadSingleFile(ftpClient, filePath,
	                        newDirPath);
	                if (success) {
	                    System.out.println("DOWNLOADED the file: " + filePath);
	                } else {
	                    System.out.println("COULD NOT download the file: "
	                            + filePath);
	                }
	            }
	        }
	    }
	    ftpClient.cdup();
	}
	    /*
	     * 
	     * Removes a non-empty directory by delete all its sub files and
	     * sub directories recursively. And finally remove the directory.
	     */
	    public static void removeDirectory(FTPClient ftpClient, String parentDir,
	            String currentDir) throws IOException {
	        String dirToList = parentDir;
	        if (!currentDir.equals("")) {
	            dirToList += hftmain.tslash + currentDir;
	        }
	        //ftpClient.cwd(skippath);
	        FTPFile[] subFiles = ftpClient.listFiles(dirToList);
	        //if (subFiles != null && subFiles.length > 0) {
	            for (FTPFile aFile : subFiles) {
	                String currentFileName = aFile.getName();
	                if (currentFileName.equals(".") || currentFileName.equals("..")) {
	                    // skip parent directory and the directory itself
	                    continue;
	                }
	                String filePath = parentDir + hftmain.tslash + currentDir + hftmain.tslash
	                        + currentFileName;
	                if (currentDir.equals("")) {
	                    filePath = parentDir + hftmain.tslash + currentFileName;
	                }
	 
	                if (aFile.isDirectory()) {
	                    // remove the sub directory
	                    removeDirectory(ftpClient, dirToList, currentFileName);
	                } else {
	                    // delete the file
	                    boolean deleted = ftpClient.deleteFile(filePath);
	                    if (deleted) {
	                        System.out.println("Deleted file: " + filePath);
	                    } else {
	                        System.out.println("CANNOT delete the file: "
	                                + filePath);
	                    }
	                }
	            }
	 
	            // finally, remove the directory itself
	            boolean removed = ftpClient.removeDirectory(dirToList);
	            if (removed) {
	                System.out.println("Removed directory: " + dirToList);
	            } else {
	                System.out.println("CANNOT remove the directory: " + dirToList);
	            }
	        //}
	    }
	    /**
	     * This method calculates total number of sub directories, files and size
	     * of a remote directory.
	     * @param ftpClient An instance of the FTPClient
	     * @param parentDir Path of the remote directory.
	     * @param currentDir The current directory (used for recursion).
	     * @return An array of long numbers in which:
	     * - the 1st number is total directories.
	     * - the 2nd number is total files.
	     * - the 3rd number is total size.
	     * @throws IOException If any I/O error occurs.
	     */
	    public static long[] calculateDirectoryInfo(FTPClient ftpClient,
	            String parentDir, String currentDir) throws IOException {
	        long[] info = new long[3];
	        long totalSize = 0;
	        int totalDirs = 0;
	        int totalFiles = 0;
	     
	        String dirToList = parentDir;
	        if (!currentDir.equals("")) {
	            dirToList += "/" + currentDir;
	        }
	     
	        try {
	            FTPFile[] subFiles = ftpClient.listFiles(dirToList);
	            int x = 0;
	            while (x < subFiles.length){
	            	System.out.println("In DirInfo");
	            	System.out.println("lf "+subFiles[x]);
	            	x++;
	            }
	            if (subFiles != null && subFiles.length > 0) {
	                for (FTPFile aFile : subFiles) {
	                    String currentFileName = aFile.getName();
	                    if (currentFileName.equals(".")
	                            || currentFileName.equals("..")) {
	                        // skip parent directory and the directory itself
	                        continue;
	                    }
	     
	                    if (aFile.isDirectory()) {
	                        totalDirs++;
	                        long[] subDirInfo =
	                                calculateDirectoryInfo(ftpClient, dirToList, currentFileName);
	                        totalDirs += subDirInfo[0];
	                        totalFiles += subDirInfo[1];
	                        totalSize += subDirInfo[2];
	                    } else {
	                        totalSize += aFile.getSize();
	                        totalFiles++;
	                    }
	                }
	            }
	     
	            info[0] = totalDirs;
	            info[1] = totalFiles;
	            info[2] = totalSize;
	     
	            return info;
	        } catch (IOException ex) {
	            throw ex;
	        }
	    }
	}



	
}

